package vehicle;

import statemap.FSMContext;
import statemap.State;
import statemap.StateUndefinedException;

public class VehicleContext extends FSMContext {

	private static final long serialVersionUID = 1L;

	public VehicleContext(Vehicle owner) {
		super(VehicleMap.Stopped);
		_owner = owner;
	}

	public VehicleContext(Vehicle owner, VehicleState initState) {
		super(initState);
		_owner = owner;
	}

	public void enterStartState() {
		getState().Entry(this);
		return;
	}

	public void Continue() {
		_transition = "Continue";
		getState().Continue(this);
		_transition = "";
		return;
	}

	public void LightGreen() {
		_transition = "LightGreen";
		getState().LightGreen(this);
		_transition = "";
		return;
	}

	public void Move() {
		_transition = "Move";
		getState().Move(this);
		_transition = "";
		return;
	}

	public void Pause() {
		_transition = "Pause";
		getState().Pause(this);
		_transition = "";
		return;
	}

	public void Start() {
		_transition = "Start";
		getState().Start(this);
		_transition = "";
		return;
	}

	public void Stop() {
		_transition = "Stop";
		getState().Stop(this);
		_transition = "";
		return;
	}

	public VehicleState getState() throws StateUndefinedException {
		if (_state == null) {
			throw (new statemap.StateUndefinedException());
		}
		return ((VehicleState) _state);
	}

	protected Vehicle getOwner() {
		return (_owner);
	}

	public void setOwner(Vehicle owner) {
		if (owner == null) {
			throw (new NullPointerException("null owner"));
		} else {
			_owner = owner;
		}
		return;
	}

	transient private Vehicle _owner;

	public static abstract class VehicleState extends State {

		private static final long serialVersionUID = 1L;

		protected VehicleState(String name, int id) {
			super(name, id);
		}

		protected void Entry(VehicleContext context) {
		}

		protected void Exit(VehicleContext context) {
		}

		protected void Continue(VehicleContext context) {
			Default(context);
		}

		protected void LightGreen(VehicleContext context) {
			Default(context);
		}

		protected void Move(VehicleContext context) {
			Default(context);
		}

		protected void Pause(VehicleContext context) {
			Default(context);
		}

		protected void Start(VehicleContext context) {
			Default(context);
		}

		protected void Stop(VehicleContext context) {
			Default(context);
		}

		protected void Default(VehicleContext context) {
			throw (new statemap.TransitionUndefinedException("State: "
					+ context.getState().getName() + ", Transition: "
					+ context.getTransition()));
		}
	}

	static abstract class VehicleMap {
		public static final VehicleMap_Stopped Stopped = new VehicleMap_Stopped(
				"VehicleMap.Stopped", 0);
		public static final VehicleMap_Moving Moving = new VehicleMap_Moving(
				"VehicleMap.Moving", 1);
		public static final VehicleMap_AtLight AtLight = new VehicleMap_AtLight(
				"VehicleMap.AtLight", 2);
		public static final VehicleMap_Done Done = new VehicleMap_Done(
				"VehicleMap.Done", 3);
		private static final VehicleMap_Default Default = new VehicleMap_Default(
				"VehicleMap.Default", -1);

		public static VehicleMap_Stopped getStopped() {
			return Stopped;
		}

		public static VehicleMap_Moving getMoving() {
			return Moving;
		}

		public static VehicleMap_AtLight getAtlight() {
			return AtLight;
		}

		public static VehicleMap_Done getDone() {
			return Done;
		}

		public static VehicleMap_Default getDefault() {
			return Default;
		}

	}

	protected static class VehicleMap_Default extends VehicleState {

		private static final long serialVersionUID = 1L;

		protected VehicleMap_Default(String name, int id) {
			super(name, id);
		}

		protected void Move(VehicleContext context) {
			return;
		}

		protected void Start(VehicleContext context) {
			return;
		}

		protected void Stop(VehicleContext context) {

			(context.getState()).Exit(context);
			context.setState(VehicleMap.Stopped);
			(context.getState()).Entry(context);
			return;
		}
	}

	private static final class VehicleMap_Stopped extends VehicleMap_Default {

		private static final long serialVersionUID = 1L;

		private VehicleMap_Stopped(String name, int id) {
			super(name, id);
		}

		protected void Continue(VehicleContext context) {

			return;
		}

		protected void Move(VehicleContext context) {

			return;
		}

		protected void Pause(VehicleContext context) {

			return;
		}

		protected void Start(VehicleContext context) {

			(context.getState()).Exit(context);
			context.setState(VehicleMap.Moving);
			(context.getState()).Entry(context);
			return;
		}

		protected void Stop(VehicleContext context) {

			return;
		}
	}

	private static final class VehicleMap_Moving extends VehicleMap_Default {

		private static final long serialVersionUID = 1L;

		private VehicleMap_Moving(String name, int id) {
			super(name, id);
		}

		protected void Move(VehicleContext context) {
			Vehicle ctxt = context.getOwner();

			if (ctxt.getXPos() < ctxt.getMinX()
					|| ctxt.getXPos() > ctxt.getMaxX()
					|| ctxt.getYPos() < ctxt.getMinY()
					|| ctxt.getYPos() > ctxt.getMaxY()) {

				(context.getState()).Exit(context);
				context.clearState();
				try {
					ctxt.EndTrip();
				} finally {
					context.setState(VehicleMap.Done);
					(context.getState()).Entry(context);
				}
			} else if (ctxt.getLightsColor() != java.awt.Color.green
					&& ctxt.getDistanceToIntersection() >= 0
					&& ctxt.getDistanceToIntersection() <= ctxt.getSpeed()) {

				(context.getState()).Exit(context);
				context.clearState();
				try {
					ctxt.Advance();
					ctxt.WatchLight();
				} finally {
					context.setState(VehicleMap.AtLight);
					(context.getState()).Entry(context);
				}
			} else {
				VehicleState endState = context.getState();

				context.clearState();
				try {
					ctxt.Advance();
				} finally {
					context.setState(endState);
				}
			}

			return;
		}
	}

	private static final class VehicleMap_AtLight extends VehicleMap_Default {

		private static final long serialVersionUID = 1L;

		private VehicleMap_AtLight(String name, int id) {
			super(name, id);
		}

		protected void LightGreen(VehicleContext context) {
			(context.getState()).Exit(context);
			context.setState(VehicleMap.Moving);
			(context.getState()).Entry(context);
			return;
		}

		protected void Move(VehicleContext context) {
			return;
		}
	}

	private static final class VehicleMap_Done extends VehicleMap_Default {

		private static final long serialVersionUID = 1L;

		private VehicleMap_Done(String name, int id) {
			super(name, id);
		}
	}
}